package com.basis.handler;

import com.basis.utils.BaseServletHandler;
import com.basis.utils.HibernateDao;
import com.basis.utils.StringUtil;
import com.mes.data.EmesFile;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.codehaus.jettison.json.JSONObject;
import org.openbravo.dal.core.OBContext;
import org.openbravo.dal.service.OBDal;
import org.openbravo.database.SessionInfo;
import org.openbravo.model.ad.access.User;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

//上传图片、文件
public class FileUploadHandler extends BaseServletHandler {
	private String tabId;
	private String dataId;

	@Override
	protected JSONObject service(HttpServletRequest request, HttpServletResponse response) {
		tabId = request.getParameter("tabId");
		dataId = request.getParameter("dataId");
		String type = request.getParameter("type");
		JSONObject result = new JSONObject();
		try {
			OBContext.setAdminMode();
			request.setCharacterEncoding("utf-8");
			List<Map<String, Object>> list = this.getTabImportObject();

			if ("getItem".equalsIgnoreCase(type)) {
				String names = "";
				String fields = "";
				for (Map<String, Object> map : list) {
					names += map.get("name") + ",";
					fields += map.get("columnname") + ",";
				}
				result.put("names", names);
				result.put("fields", fields);
				result.put("result", true);
			} else {
				Map<String, Map<String, Object>> fieldMap = new HashMap();
				for (Map<String, Object> map : list) {
					fieldMap.put(map.get("columnname").toString().toUpperCase(), map);
				}

				DiskFileItemFactory factory = new DiskFileItemFactory();
				// 设置 缓存的大小，当上传文件的容量超过该缓存时，直接放到 暂时存储室
				factory.setSizeThreshold(1024 * 1024);
				ServletFileUpload upload = new ServletFileUpload(factory);

				// 可以上传多个文件
				List<FileItem> listItem = (List<FileItem>) upload.parseRequest(request);
				for (FileItem item : listItem) {
					if (item.getName() == null || "".equals(item.getName().trim())) {
						// 不含文件内容
						continue;
					}

					String fieldName = item.getFieldName().toUpperCase();
					uploadFile(item, fieldMap.get(fieldName));
				}
				result.put("desc", "上传成功！");
				result.put("result", true);

				OBDal.getInstance().commitAndClose();
			}
		} catch (Exception e) {
			e.printStackTrace();
			OBDal.getInstance().rollbackAndClose();
			try {
				result.put("desc", e.getMessage());
				result.put("result", false);
			} catch (Exception ex){}
		} finally {
			OBContext.restorePreviousMode();
		}
		return result;
	}

	/**
	 * 上传文件
	 * @param item
	 * @param map
	 */
	private void uploadFile(FileItem item, Map<String, Object> map) throws Exception {
		String savePath = (String)map.get("upload_path");
		File file = new File(savePath);

		if (!file.exists() && !file.isDirectory()) {
			//创建目录
			file.mkdirs();
		}
		String fileName = item.getName();
		if (map.get("file_type") != null && !"".equals(map.get("file_type").toString())) {
			String[] endWith = map.get("file_type").toString().split("\\|");
			boolean pass = false;
			for (String end : endWith) {
				if (fileName.endsWith(end)) {
					pass = true;
				}
			}
			if (!pass) {
				throw new RuntimeException("上传的文件后缀必须是：" + map.get("file_type"));
			}
		}
		InputStream in = item.getInputStream();

		String oldPix = fileName.substring(fileName.lastIndexOf("."));
		fileName = System.currentTimeMillis() + oldPix;
		FileOutputStream out = new FileOutputStream(savePath + "\\" + fileName);

		//创建一个缓冲区
		byte buffer[] = new byte[1024];
		//判断输入流中的数据是否已经读完的标识
		int len = 0;
		//循环将输入流读入到缓冲区当中，(len=in.read(buffer))>0就表示in里面还有数据
		while ((len = in.read(buffer)) > 0) {
			//使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\" + filename)当中
			out.write(buffer, 0, len);
		}
		//关闭输入流
		in.close();
		//关闭输出流
		out.close();

		//如果是文件上传页面，则直接只做修改
		if ("emes_file".equalsIgnoreCase(map.get("tablename").toString())) {
			updateFile(savePath + "\\" + fileName, item.getName());
		} else {
			//保存文件数据
			String fileId = saveFile(savePath + "\\" + fileName, item.getName(), (String)map.get("tablename"));
			//更新当前上传记录行的文件ID
			String sql = "update " + map.get("tablename") + " set " + map.get("columnname") +
					" = ? where " + map.get("tablename") + "_id = ?";
			HibernateDao.executeSql(sql, fileId, dataId);
		}
	}

	/**
	 * 根据页签ID获取配置的上传文件字段
	 * @return
	 */
	private List<Map<String, Object>> getTabImportObject() {
		String sql = "select \n" +
				"\t\t(select columnname from ad_column c where c.ad_column_id = f.ad_column_id) columnname,\n" +
				"\t\t(select tablename from ad_table tb where tb.ad_table_id = t.ad_table_id) tablename,\n" +
				"\t\tfi.name, fi.upload_path, fi.file_type, fi.description\n" +
				"  from ad_field f, ad_tab t, emes_file_import fi\n" +
				" where f.ad_field_id = fi.ad_field_id\n" +
				"   and t.ad_tab_id = fi.ad_tab_id\n" +
				"\t and fi.ad_tab_id = ?";
		return HibernateDao.query(sql, tabId);
	}

	/**
	 * 存储文件到文件表
	 * @param path
	 * @param name
	 * @param tableName
	 * @return
	 */
	private String saveFile(String path, String name, String tableName) {
		String fileId = StringUtil.getUUID();
		String userId = SessionInfo.getUserId();
		User user = OBDal.getInstance().get(User.class, userId);
		String code = name.substring(0, name.lastIndexOf("."));
		String type = name.substring(name.lastIndexOf(".") + 1);

		String sql = "insert into emes_file(emes_file_id, code, name, path, table_name, type, ad_client_id, ad_org_id, createdby, updatedby)" +
				"values (?, ?, ?, ?, ?, ?, ?, ?, ?,?)";
		HibernateDao.executeSql(sql, fileId, code, name, path, tableName, type.toUpperCase(), user.getClient().getId(),
				user.getOrganization().getId(), user.getId(), user.getId());
		return fileId;
	}

	private void updateFile(String path, String name) {
		String code = name.substring(0, name.lastIndexOf("."));
		String type = name.substring(name.lastIndexOf(".") + 1);

		EmesFile file = OBDal.getInstance().get(EmesFile.class, dataId);
		file.setPath(path);
		file.setName(name);
		file.setCode(code);
		file.setType(type);

		OBDal.getInstance().save(file);
	}
}